// Package wechat exposes high-level typed API wrappers for WeChat Pay v3.
package wechat

import (
    "encoding/json"
    "fmt"
)

// API 定义对上层暴露的微信能力接口，便于切换真实/模拟实现
type API interface {
    SendCashCoupon(req SendCashCouponRequest) (*SendCashCouponResponse, error)
    CreateDiscountActivity(req CreateDiscountActivityRequest) (*CreateDiscountActivityResponse, error)
    CreateRandomDiscount(req CreateRandomDiscountRequest) (*CreateRandomDiscountResponse, error)
    QueryTransactionByOutTradeNo(mchID, outTradeNo string) (*QueryTransactionResponse, error)
    UploadNumberPackage(req UploadNumberPackageRequest) (*UploadNumberPackageResponse, error)
    ListNumberPackageUsers(packageID string, offset, limit int) (*ListNumberPackageUsersResponse, error)
}

const baseURL = "https://api.mch.weixin.qq.com"

// 3.1 立减金发放接口
type SendCashCouponRequest struct {
	CouponID  string `json:"coupon_id"`
	OpenID    string `json:"openid"`
	SendName  string `json:"send_name"`
	Remark    string `json:"remark,omitempty"`
	NotifyURL string `json:"notify_url,omitempty"`
}

type SendCashCouponResponse struct {
	ReturnCode string `json:"return_code"`
	ReturnMsg  string `json:"return_msg"`
	ResultCode string `json:"result_code"`
	ErrCode    string `json:"err_code,omitempty"`
	ErrCodeDes string `json:"err_code_des,omitempty"`
	CouponID   string `json:"coupon_id,omitempty"`
	SendTime   string `json:"send_time,omitempty"`
	SendNo     string `json:"send_no,omitempty"`
}

func (c *Client) SendCashCoupon(req SendCashCouponRequest) (*SendCashCouponResponse, error) {
	if req.NotifyURL == "" && c.config.NotifyURL != "" {
		req.NotifyURL = c.config.NotifyURL
	}
	url := baseURL + "/v3/promotion/cashcoupons/send"
	data, err := c.doRequest("POST", url, req)
	if err != nil {
		return nil, err
	}
	var resp SendCashCouponResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}

// 3.2 平台立减接口
type CreateDiscountActivityRequest struct {
	ActivityName  string `json:"activity_name"`
	StartTime     string `json:"start_time"`
	EndTime       string `json:"end_time"`
	DiscountType  string `json:"discount_type"` // FIXED_AMOUNT / PERCENTAGE
	DiscountValue int    `json:"discount_value"`
	MinSpend      int    `json:"min_spend"`
	MaxDiscount   *int   `json:"max_discount,omitempty"`
}

type CreateDiscountActivityResponse struct {
	ReturnCode string `json:"return_code"`
	ReturnMsg  string `json:"return_msg"`
	ResultCode string `json:"result_code"`
	ErrCode    string `json:"err_code,omitempty"`
	ErrCodeDes string `json:"err_code_des,omitempty"`
	ActivityID string `json:"activity_id,omitempty"`
	CreateTime string `json:"create_time,omitempty"`
}

func (c *Client) CreateDiscountActivity(req CreateDiscountActivityRequest) (*CreateDiscountActivityResponse, error) {
	url := baseURL + "/v3/promotion/discountactivity/create"
	data, err := c.doRequest("POST", url, req)
	if err != nil {
		return nil, err
	}
	var resp CreateDiscountActivityResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}

// 3.3 随机减接口
type CreateRandomDiscountRequest struct {
	ActivityName string `json:"activity_name"`
	StartTime    string `json:"start_time"`
	EndTime      string `json:"end_time"`
	MinDiscount  int    `json:"min_discount"`
	MaxDiscount  int    `json:"max_discount"`
	MinSpend     int    `json:"min_spend"`
	Probability  int    `json:"probability"`
}

type CreateRandomDiscountResponse struct {
	ReturnCode string `json:"return_code"`
	ReturnMsg  string `json:"return_msg"`
	ResultCode string `json:"result_code"`
	ErrCode    string `json:"err_code,omitempty"`
	ErrCodeDes string `json:"err_code_des,omitempty"`
	ActivityID string `json:"activity_id,omitempty"`
	CreateTime string `json:"create_time,omitempty"`
}

func (c *Client) CreateRandomDiscount(req CreateRandomDiscountRequest) (*CreateRandomDiscountResponse, error) {
	url := baseURL + "/v3/promotion/randomdiscount/create"
	data, err := c.doRequest("POST", url, req)
	if err != nil {
		return nil, err
	}
	var resp CreateRandomDiscountResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}

// 3.4 交易结果查询接口（按商户订单号）
type QueryTransactionResponse struct {
	ReturnCode    string `json:"return_code"`
	ReturnMsg     string `json:"return_msg"`
	ResultCode    string `json:"result_code"`
	ErrCode       string `json:"err_code,omitempty"`
	ErrCodeDes    string `json:"err_code_des,omitempty"`
	TransactionID string `json:"transaction_id,omitempty"`
	OutTradeNo    string `json:"out_trade_no,omitempty"`
	TotalFee      int    `json:"total_fee,omitempty"`
	ActualFee     int    `json:"actual_fee,omitempty"`
	DiscountFee   int    `json:"discount_fee,omitempty"`
	TradeState    string `json:"trade_state,omitempty"`
	TimeEnd       string `json:"time_end,omitempty"`
}

func (c *Client) QueryTransactionByOutTradeNo(mchID, outTradeNo string) (*QueryTransactionResponse, error) {
	path := fmt.Sprintf("/v3/pay/transactions/out-trade-no/%s?mch_id=%s", outTradeNo, mchID)
	url := baseURL + path
	data, err := c.doRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	var resp QueryTransactionResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}

// 3.5 号码包上传（简化：仅记录元数据，文件上传流程由上层处理）
type UploadNumberPackageRequest struct {
	PackageName string `json:"package_name"`
	PackageDesc string `json:"package_desc,omitempty"`
	UserCount   int    `json:"user_count"`
	FileURL     string `json:"file_url"`
	FileMD5     string `json:"file_md5"`
}

type UploadNumberPackageResponse struct {
	ReturnCode string `json:"return_code"`
	ReturnMsg  string `json:"return_msg"`
	ResultCode string `json:"result_code"`
	ErrCode    string `json:"err_code,omitempty"`
	ErrCodeDes string `json:"err_code_des,omitempty"`
	PackageID  string `json:"package_id,omitempty"`
	UploadTime string `json:"upload_time,omitempty"`
}

func (c *Client) UploadNumberPackage(req UploadNumberPackageRequest) (*UploadNumberPackageResponse, error) {
	url := baseURL + "/v3/promotion/numberpackages/upload"
	data, err := c.doRequest("POST", url, req)
	if err != nil {
		return nil, err
	}
	var resp UploadNumberPackageResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}

// 3.6 号码包内用户名单查询
type ListNumberPackageUsersResponse struct {
	ReturnCode string `json:"return_code"`
	ReturnMsg  string `json:"return_msg"`
	ResultCode string `json:"result_code"`
	ErrCode    string `json:"err_code,omitempty"`
	ErrCodeDes string `json:"err_code_des,omitempty"`
	TotalCount int    `json:"total_count,omitempty"`
	UserList   []struct {
		OpenID     string `json:"openid"`
		CreateTime string `json:"create_time"`
	} `json:"user_list,omitempty"`
}

func (c *Client) ListNumberPackageUsers(packageID string, offset, limit int) (*ListNumberPackageUsersResponse, error) {
	if limit <= 0 {
		limit = 100
	}
	path := fmt.Sprintf("/v3/promotion/numberpackages/%s/users?offset=%d&limit=%d", packageID, offset, limit)
	url := baseURL + path
	data, err := c.doRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	var resp ListNumberPackageUsersResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}
